Directory Favorite List - Felix John COLIBRI. |
- abstract : a tListBox allowing quick selection of the current tDirectoryListbox directory
- key words : tDirectoryListBox
- software used : Windows 10 pro, Delphi 7
- hardware used : Intel I3 3.6 Ghz, 8 G memory, 1 Tera hard disc
- scope : Delphi 1 to 7, 2005 to 2010, Delphi Xe, Berlin, Tokyo
- level : Delphi developer
- plan :
1 - Directory Favorite List When we are handling projects with some deeply nested file structure, the Windows File Explorer does not allow quick moves from one directory to an
other. The purpose of the favorite list component is - to display in a tListBox the names of our favorite pathes
- to set the current Windows directory by simply clicking on one of those names
2 - Mini How To Nearly all of our Delphi utilities main window use the following structure: - on the left
- a directory favorite list
- a tDirectoryListBox
- a tFileListBox
- on the right, a display area (a tMemo)
and : - to ad an item to the favorite list,
- to delete a favorite
| select the favorite item to delete | | type "-" |
- to reorder the items, use drag and drop
- to navigate to one of the directories, we simply click the item in the favorite list
3 - the Delphi source code
The code is very straightforward - the c_favorite_path is defined by :
c_favorite_path= // one "favorite_path" Class(c_basic_object)
// -- m_name: the displayed name in the memos
// -- the m_parameter is not currently used (could be a Mask)
m_path, m_parameter: String;
Constructor create_favorite_path(p_name, p_path, p_parameter: String);
Function f_display_favorite_path: String;
Function f_c_self: c_favorite_path;
Function f_normalized_parameter_list: String;
Destructor Destroy; Override;
End; // c_favorite_path | where - m_name is the item name
- m_path is the directory
- the list of favorites is managed by a tStringList container:
c_favorite_path_list= // "favorite_path" list Class(c_basic_object)
// -- m_name: the full file name
m_c_favorite_path_list: tStringList;
m_c_directory_listbox_ref: tDirectoryListbox;
m_c_panel_ref: tPanel; m_c_list_box: tListBox;
m_full_file_name: String;
Constructor create_favorite_path_list(p_name: String;
p_c_panel_ref: tPanel;
p_c_directory_listbox_ref: tDirectoryListbox);
Function f_favorite_path_count: Integer;
Function f_c_favorite_path(p_favorite_path_index: Integer): c_favorite_path;
Function f_index_of(p_favorite_path_name: String): Integer;
Function f_c_find_by_favorite_path(p_favorite_path_name: String): c_favorite_path;
Procedure add_favorite_path(p_favorite_path_name: String;
p_c_favorite_path: c_favorite_path);
Function f_c_add_favorite_path(p_favorite_path_name, p_path, p_parameter: String):
c_favorite_path;
Function f_c_add_unique_favorite_path(p_favorite_path_name, p_path,
p_parameter: String): c_favorite_path;
Function f_c_delete_favorite_path(p_favorite_path_index: Integer): c_favorite_path;
Procedure display_favorite_path_list;
Function f_path_name_index(p_path_name: String): Integer;
Procedure create_listbox;
Procedure handle_favorite_listbox_click(p_c_sender: tObject);
Procedure handle_listbox_keypress(p_c_sender: tObject; Var pv_key: Char);
Procedure handle_directory_listbox_keypress(p_c_sender: tObject; Var pv_key: Char);
Procedure handle_directory_listbox_click(p_c_sender: tObject);
Procedure handle_directory_listbox_drag_over(
p_c_sender, p_c_source: TObject; p_x, p_y: Integer;
p_drag_state: TDragState; Var pv_accept: Boolean);
Procedure handle_directory_listbox_drag_dop(
p_c_sender, p_c_source: TObject; p_x, p_y: Integer);
Procedure load_from_file(p_full_file_name: String);
Procedure save_to_file;
Destructor Destroy; Override;
End; // c_favorite_path_list | The class contains
- a reference to the tDirectoryLisbox (to handle the "+" and the directory selection
- a reference to the favorite list panel. The favorite tListbox will be dynamically create with this panel as it's parent
Procedure c_favorite_path_list.handle_directory_listbox_drag_over(
p_c_sender, p_c_source: TObject; p_x, p_y: Integer;
p_drag_state: TDragState; Var pv_accept: Boolean);
Begin pv_accept := p_c_sender= p_c_source;
End; // handle_directory_listbox_drag_over
Procedure c_favorite_path_list.handle_directory_listbox_drag_dop(
p_c_sender, p_c_source: TObject; p_x, p_y: Integer);
Var l_item_index, l_drop_index: Integer; Begin
With m_c_list_box Do Begin
l_drop_index:= ItemAtPos(Point(p_x, p_y), True);
If l_drop_index< 0
Then l_drop_index:= 0;
If l_drop_index>= Count
Then l_drop_index:= Count- 1;
// -- ItemIndex will be changed by the Exchange
l_item_index:= ItemIndex;
If l_drop_index= l_item_index
Then Exit;
Items.Exchange(ItemIndex, l_drop_index);
m_c_favorite_path_list.Exchange(l_item_index, l_drop_index);
End; // with m_c_list_box save_to_file;
End; // handle_directory_listbox_drag_dop |
and
- m_c_favorite_path_list is the container, with the usual count, add, display routines
- clicking on the favorite list selects the appropriate directory
Procedure c_favorite_path_list.handle_favorite_listbox_click(p_c_sender: tObject);
Var l_c_favorite_path: c_favorite_path; Begin
With m_c_list_box Do
l_c_favorite_path:= f_c_find_by_favorite_path(Items[ItemIndex]);
With l_c_favorite_path Do
set_directory_listbox_directory(m_c_directory_listbox_ref, m_path);
End; // handle_favorite_listbox_click | - clicking "-" removes the favorite item from the list
Procedure c_favorite_path_list.handle_listbox_keypress(p_c_sender: tObject; Var pv_key: Char);
Var l_favorite_index: integer; Begin
If pv_key= '-'
Then Begin
With m_c_list_box Do
Begin
l_favorite_index:= ItemIndex;
Items.Delete(l_favorite_index);
End; // -- remove from list
f_c_delete_favorite_path(l_favorite_index).Free;
save_to_file; End;
End; // handle_listbox_keypress | - clicking "+" in the tDirectoryListbox adds another favorite item :
Procedure c_favorite_path_list.handle_directory_listbox_keypress(
p_c_sender: tObject; Var pv_key: Char);
Var l_path_name, l_path: String;
l_c_favorite_path: c_favorite_path;
l_path_index: Integer;
l_found_path: Boolean; Begin
If pv_key= '+'
Then Begin
l_path_name:= f_input_string(10, 10, 'enter path name', k_letters+ k_digits+ ['_']);
With m_c_directory_listbox_ref Do
l_path:= GetItemPath(ItemIndex)+ '\';
With m_c_favorite_path_list Do
Begin
l_found_path:= False;
For l_path_index:= 0 To Count- 1 Do
With f_c_favorite_path(l_path_index) Do
If SameText(l_path, m_path)
Then Begin
l_found_path:= True;
m_name:= l_path_name;
m_c_favorite_path_list[l_path_index]:= l_path_name;
m_c_list_box.Items[l_path_index]:= l_path_name;
Break;
End;
If Not l_found_path
Then Begin
l_c_favorite_path:= f_c_add_unique_favorite_path(l_path_name, l_path, '*');
With m_c_list_box.Items Do
AddObject(l_path_name, l_c_favorite_path);
End;
End; // with m_c_favorite_path_list
display_favorite_path_list; save_to_file;
End; End; // handle_directory_listbox_keypress |
- reordering the items is handled by drag and drop
Procedure c_favorite_path_list.handle_directory_listbox_drag_over(
p_c_sender, p_c_source: TObject; p_x, p_y: Integer;
p_drag_state: TDragState; Var pv_accept: Boolean);
Begin pv_accept := p_c_sender= p_c_source;
End; // handle_directory_listbox_drag_over
Procedure c_favorite_path_list.handle_directory_listbox_drag_dop(
p_c_sender, p_c_source: TObject; p_x, p_y: Integer);
Var l_item_index, l_drop_index: Integer; Begin
With m_c_list_box Do Begin
l_drop_index:= ItemAtPos(Point(p_x, p_y), True);
If l_drop_index< 0
Then l_drop_index:= 0;
If l_drop_index>= Count
Then l_drop_index:= Count- 1;
// -- ItemIndex will be changed by the Exchange
l_item_index:= ItemIndex;
If l_drop_index= l_item_index
Then Exit;
Items.Exchange(ItemIndex, l_drop_index);
m_c_favorite_path_list.Exchange(l_item_index, l_drop_index);
End; // with m_c_list_box save_to_file;
End; // handle_directory_listbox_drag_dop |
Of course, much could be improved:
- we could use Delphi generics instead of our own container
- in our code, we directly created the tDirectoryListbox OnKeyDown event handlers. The user of this utility could not blindly use his own event
handler. To solve then we should have overwritten the Click dispatcher.
4 - Download the Sources Here are the source code files: The .ZIP file(s) contain: - the main program (.DPR, .DOF, .RES), the main form (.PAS, .DFM), and any other auxiliary form
- any .TXT for parameters, samples, test data
- all units (.PAS) for units
Those .ZIP - are self-contained: you will not need any other product (unless expressly mentioned).
- for Delphi 6 projects, can be used from any folder (the pathes are RELATIVE)
- will not modify your PC in any way beyond the path where you placed the .ZIP (no registry changes, no path creation etc).
To use the .ZIP:
- create or select any folder of your choice
- unzip the downloaded file
- using Delphi, compile and execute
To remove the .ZIP simply delete the folder.
The Pascal code uses the Alsacian notation, which prefixes identifier by program area: K_onstant, T_ype, G_lobal, L_ocal, P_arametre, F_unction, C_lass etc. This notation is presented in the Alsacian Notation paper.
As usual:
- please tell us at fcolibri@felix-colibri.com if you found some errors, mistakes, bugs, broken links or had some problem downloading the file. Resulting corrections will
be helpful for other readers
- we welcome any comment, criticism, enhancement, other sources or reference suggestion. Just send an e-mail to fcolibri@felix-colibri.com.
- or more simply, enter your (anonymous or with your e-mail if you want an answer) comments below and clic the "send" button
- and if you liked this article, talk about this site to your fellow developpers, add a link to your links page ou mention our articles in your blog or newsgroup posts when relevant. That's the way we operate:
the more traffic and Google references we get, the more articles we will write.
5 - The author Felix John COLIBRI works at the Pascal
Institute. Starting with Pascal in 1979, he then became involved with Object Oriented Programming, Delphi, Sql, Tcp/Ip, Html, UML. Currently, he is mainly
active in the area of custom software development (new projects, maintenance, audits, BDE migration, Delphi
Xe_n migrations, refactoring), Delphi Consulting and Delph
training. His web site features tutorials, technical papers about programming with full downloadable source code, and the description and calendar of forthcoming Delphi, FireBird, Tcp/IP, Web Services, OOP / UML, Design Patterns, Unit Testing training sessions. |